<template>
  <div class="box_model" style="position: relative">
    <div ref="webglRef" class="canvas" />
    <div
      v-show="showFullIcon"
      @click="gotoFull"
      style="
        position: absolute;
        top: 10px;
        left: 10px;
        padding: 10px;
        color: white;
      "
    >
      <el-icon color="white" size="20"><FullScreen /></el-icon>
    </div>
    <div @click='checkClose' class="box_model_bg_button">碰撞</div>
    <div
      v-show="!showFullIcon"
      @click="CloseFull"
      style="
        position: absolute;
        top: 10px;
        left: 10px;
        padding: 10px;
        color: white;
      "
    >
      <el-icon color="white" size="20"><CircleClose /></el-icon>
    </div>

    <div class="bottom_bar">
      <div style="color: white; font-size: 14px" class="item_buttom">
        当前视图：{{ cameraType }}
      </div>
      <div
        style="
          display: flex;
          align-items: center;
          justify-content: space-between;
          width: 38%;
        "
      >
        <div @click="cameraPostionChange(1)" class="item_buttom">
          <el-tooltip
            class="box-item"
            effect="dark"
            content="正视图"
            placement="top-start"
          >
            <img width="20" height="20" src="/src/assets/zs.png" alt="" />
          </el-tooltip>
        </div>
        <div @click="cameraPostionChange(2)" class="item_buttom">
          <el-tooltip
            class="box-item"
            effect="dark"
            content="俯视图"
            placement="top-start"
          >
            <img width="20" height="20" src="/src/assets/fs.png" alt="" />
          </el-tooltip>
        </div>
        <div @click="cameraPostionChange(3)" class="item_buttom">
          <el-tooltip
            class="box-item"
            effect="dark"
            content="侧视图"
            placement="top-start"
          >
            <img width="20" height="20" src="/src/assets/ss.png" alt="" />
          </el-tooltip>
        </div>
        <div @click="cameraPostionChange(4)" class="item_buttom">
          <el-tooltip
            class="box-item"
            effect="dark"
            content="重置视图"
            placement="top-start"
          >
            <img width="20" height="20" src="/src/assets/cz.png" alt="" />
          </el-tooltip>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { useEquipmentStore } from "/@/stores/equipment";
import { CSG } from "three-csg-ts";
import { FullScreen, CircleClose } from "@element-plus/icons-vue";
import * as THREE from "three";
import * as SHAPE from "/@/threejs/equipment";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import {
  CSS2DRenderer,
  CSS2DObject,
} from "three/examples/jsm/renderers/CSS2DRenderer.js";
import {
  scene,
  material,
  camera as PerspectiveCamera,
  render,
  pointLight,
} from "/@/threejs/index";
import { hasModel, hasModelObj } from "/@/threejs/const";
import { ElMessage, ElNotification } from "element-plus";
import * as dat from "dat.gui";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import TWEEN from "@tweenjs/tween.js";
import {
  ref,
  toRefs,
  reactive,
  onMounted,
  onBeforeUnmount,
  defineProps,
  watch,
} from "vue";
// import * as TWEEN from 'tween.js';
// 定义Props
let props = defineProps([
  "shapesDataCal",
  "nozzlesDataCal",
  "CalPipeSuppPreWeld",
  "PlantformPreWeldedPart",
  "canvasWidth",
  "canvasHeight",
]);

let EquipmentStore = useEquipmentStore();

let cameraType = ref("正交视图");
let camera = PerspectiveCamera;
let emit = defineEmits(["initFinsh", "initImgFinsh"]);

let oldWidth = ref(0);
let oldHeight = ref(0);
let showFullIcon = ref(true);
let gotoFull = () => {
  showFullIcon.value = false;
  let dom = document.querySelector(".box_model");
  oldWidth = dom.clientWidth;
  oldHeight = dom.clientHeight;

  let width = window.innerWidth;
  let height = window.innerHeight;

  dom.style.zIndex = 999999;

  dom.style.top = 0;
  dom.style.left = 0;

  render.setSize(width, height);
  camera.left = -width;
  camera.right = width;
  camera.top = height;
  camera.bottom = -height;

  camera.zoom = 8;
  //更新摄像机的投影举证
  camera.updateProjectionMatrix();
  // 重置场景的size
  render.setSize(window.innerWidth, window.innerHeight);
  // 重置像素比
  render.setPixelRatio(window.devicePixelRatio);

  setTimeout(() => {
    dom.style.width = width + "px";
    dom.style.height = height + "px";
    dom.style.position = "fixed";
  }, 20);

  window.addEventListener("resize", () => {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    render.setSize(window.innerWidth, window.innerHeight);
    // 重置像素比
    render.setPixelRatio(window.devicePixelRatio);
  });
};

let CloseFull = () => {
  showFullIcon.value = true;
  let dom = document.querySelector(".box_model");

  let width = oldWidth;
  let height = oldHeight;

  dom.style.zIndex = 0;

  dom.style.top = 0;
  dom.style.left = 0;
  camera.left = -width / 2;
  camera.right = width / 2;
  camera.top = height / 2;
  camera.bottom = -height / 2;

  render.setSize(width, height);
  camera.zoom = 4;
  //更新摄像机的投影举证
  camera.updateProjectionMatrix();
  // 重置场景的size
  render.setSize(oldWidth, oldHeight);
  // 重置像素比
  render.setPixelRatio(window.devicePixelRatio);

  setTimeout(() => {
    dom.style.width = width + "px";
    dom.style.height = height + "px";
    dom.style.position = "relative";
  }, 20);
};

// 定义变量内容
let shapeGroup = new THREE.Group();
let nozzleGroup = new THREE.Group();
let webglRef = ref();

let cameraPostionChange = (num) => {
  if (num == 1) {
    new TWEEN.Tween(camera.position)
      .to({ x: 0, y: 30, z: 158 }, 1000)
      .onUpdate(() => {
        camera.lookAt(0, 30, 0);
        camera.zoom = 5;
        controls.target.set(0, 30, 0);
        camera.updateProjectionMatrix();
      })
      .start();
  }
  if (num == 2) {
    new TWEEN.Tween(camera.position)
      .to({ x: 0, y: 95.3, z: 0 }, 1000)
      .onUpdate(() => {
        camera.lookAt(0, 0, 0);
        camera.zoom = 2;
        controls.target.set(0, 0, 0);
        camera.updateProjectionMatrix();
      })
      .start();
  }
  if (num == 3) {
    new TWEEN.Tween(camera.position)
      .to({ x: 158, y: 20, z: 0 }, 1000)
      .onUpdate(() => {
        camera.lookAt(0, 20, 0);
        camera.zoom = 5;
        controls.target.set(0, 20, 0);
        camera.updateProjectionMatrix();
      })
      .start();
  }
  if (num == 4) {
    new TWEEN.Tween(camera.position)
      .to({ x: 72, y: 109, z: 86 }, 1000)
      .onUpdate(() => {
        camera.lookAt(0, 0, 0);
        camera.zoom = 5;
        controls.target.set(0, 0, 0);
        camera.updateProjectionMatrix();
      })
      .start();
  }
};

// 定义函数内容
function shapeModel() {
  scene.remove(shapeGroup);
  shapeGroup.children.splice(0, shapeGroup.children.length);

  // TODO: 遍历基本体数据建模
  let shapesData = props.shapesDataCal;
  for (let shapeData of shapesData) {
    createShapeModel(shapeData);
  }
  // 渲染模型
  scene.add(shapeGroup);
  render.render(scene, camera);
  webglRef.value?.appendChild(render?.domElement);
}

function nozzleModel() {
  scene.remove(nozzleGroup);
  nozzleGroup.children.splice(0, nozzleGroup.children.length);

  // TODO: 遍历管口数据建模
  let nozzlesData = props.nozzlesDataCal;
  for (let nozzleData of nozzlesData) {
    createNozzleModel(nozzleData);
  }
  // 渲染模型
  scene.add(nozzleGroup);
  render.render(scene, camera);
  webglRef.value?.appendChild(render?.domElement);
}

// 创建基本体
function createShapeModel(shapeData) {
  switch (shapeData["shape_type"]) {
    case "Cylinder":
      let cylinder = SHAPE.AddCylinder2(
        Number(shapeData["Point1X"]) / 100,
        Number(shapeData["Point1Y"]) / 100,
        Number(shapeData["Point1Z"]) / 100,
        Number(shapeData["Point2X"]) / 100,
        Number(shapeData["Point2Y"]) / 100,
        Number(shapeData["Point2Z"]) / 100,
        Number(shapeData["A"]) / 100,
        Number(shapeData["B"]) / 100,
        material
      );
      shapeGroup.add(cylinder);
      break;

      case "Cylinder_吊耳":
      let cylinder_ = SHAPE.AddCylinder2(
        Number(shapeData["Point1X"]) / 100,
        Number(shapeData["Point1Y"]) / 100,
        Number(shapeData["Point1Z"]) / 100,
        Number(shapeData["Point2X"]) / 100,
        Number(shapeData["Point2Y"]) / 100,
        Number(shapeData["Point2Z"]) / 100,
        Number(shapeData["A"]) / 100,
        Number(shapeData["B"]) / 100,
        material
      );
      shapeGroup.add(cylinder_);
      break;


    case "Cone":
      let cone = SHAPE.AddCone(
        Number(shapeData["Point1X"]) / 100,
        Number(shapeData["Point1Y"]) / 100,
        Number(shapeData["Point1Z"]) / 100,
        Number(shapeData["Point2X"]) / 100,
        Number(shapeData["Point2Y"]) / 100,
        Number(shapeData["Point2Z"]) / 100,
        Number(shapeData["A"]) / 100,
        Number(shapeData["B"]) / 100,
        Number(shapeData["C"]) / 100,
        material
      );
      shapeGroup.add(cone);
      break;
    // 偏心椎壳
    case "EccCone":
      let eccCone = SHAPE.AddEccCone(
        Number(shapeData["Point1X"]) / 100,
        Number(shapeData["Point1Y"]) / 100,
        Number(shapeData["Point1Z"]) / 100,
        Number(shapeData["Point2X"]) / 100,
        Number(shapeData["Point2Y"]) / 100,
        Number(shapeData["Point2Z"]) / 100,
        Number(shapeData["A"]) / 100,
        Number(shapeData["B"]) / 100,
        Number(shapeData["C"]) / 100,
        material
      );
      shapeGroup.add(eccCone);
      break;

    // 封头
    case "EHA":
      let eha = SHAPE.AddHead2(
        Number(shapeData["Point1X"]) / 100,
        Number(shapeData["Point1Y"]) / 100,
        Number(shapeData["Point1Z"]) / 100,
        Number(shapeData["Point2X"]) / 100,
        Number(shapeData["Point2Y"]) / 100,
        Number(shapeData["Point2Z"]) / 100,
        Number(shapeData["A"]) / 100,
        Number(shapeData["B"]) / 100,
        material
      );
      shapeGroup.add(eha);
      break;

    // 鞍座
    case "Pyramid":
      let pyramid = SHAPE.AddPyramid(
        Number(shapeData["Point1X"]) / 100,
        Number(shapeData["Point1Y"]) / 100,
        Number(shapeData["Point1Z"]) / 100,
        Number(shapeData["Point2X"]) / 100,
        Number(shapeData["Point2Y"]) / 100,
        Number(shapeData["Point2Z"]) / 100,
        Number(shapeData["Point3X"]) / 100,
        Number(shapeData["Point3Y"]) / 100,
        Number(shapeData["Point3Z"]) / 100,
        Number(shapeData["Point4X"]) / 100,
        Number(shapeData["Point4Y"]) / 100,
        Number(shapeData["Point4Z"]) / 100,
        Number(shapeData["A"]) / 100,
        Number(shapeData["B"]) / 100,
        Number(shapeData["C"]) / 100,
        Number(shapeData["D"]) / 100,
        Number(shapeData["E"]) / 100,
        material
      );
      shapeGroup.add(pyramid);
      break;

      // 鞍座
    case "Pyramid_耳座":
      let pyramid___ = SHAPE.AddPyramid(
        Number(shapeData["Point1X"]) / 100,
        Number(shapeData["Point1Y"]) / 100,
        Number(shapeData["Point1Z"]) / 100,
        Number(shapeData["Point2X"]) / 100,
        Number(shapeData["Point2Y"]) / 100,
        Number(shapeData["Point2Z"]) / 100,
        Number(shapeData["Point3X"]) / 100,
        Number(shapeData["Point3Y"]) / 100,
        Number(shapeData["Point3Z"]) / 100,
        Number(shapeData["Point4X"]) / 100,
        Number(shapeData["Point4Y"]) / 100,
        Number(shapeData["Point4Z"]) / 100,
        Number(shapeData["A"]) / 100,
        Number(shapeData["B"]) / 100,
        Number(shapeData["C"]) / 100,
        Number(shapeData["D"]) / 100,
        Number(shapeData["E"]) / 100,
        material
      );
      shapeGroup.add(pyramid___);
      break;

      // 鞍座
    case "Pyramid_鞍座滑":
      let pyramid_ = SHAPE.AddPyramid(
        Number(shapeData["Point1X"]) / 100,
        Number(shapeData["Point1Y"]) / 100,
        Number(shapeData["Point1Z"]) / 100,
        Number(shapeData["Point2X"]) / 100,
        Number(shapeData["Point2Y"]) / 100,
        Number(shapeData["Point2Z"]) / 100,
        Number(shapeData["Point3X"]) / 100,
        Number(shapeData["Point3Y"]) / 100,
        Number(shapeData["Point3Z"]) / 100,
        Number(shapeData["Point4X"]) / 100,
        Number(shapeData["Point4Y"]) / 100,
        Number(shapeData["Point4Z"]) / 100,
        Number(shapeData["A"]) / 100,
        Number(shapeData["B"]) / 100,
        Number(shapeData["C"]) / 100,
        Number(shapeData["D"]) / 100,
        Number(shapeData["E"]) / 100,
        material
      );
      shapeGroup.add(pyramid_);
      break;




         // 鞍座
    case "Pyramid_鞍座固":
      let pyramid__ = SHAPE.AddPyramid(
        Number(shapeData["Point1X"]) / 100,
        Number(shapeData["Point1Y"]) / 100,
        Number(shapeData["Point1Z"]) / 100,
        Number(shapeData["Point2X"]) / 100,
        Number(shapeData["Point2Y"]) / 100,
        Number(shapeData["Point2Z"]) / 100,
        Number(shapeData["Point3X"]) / 100,
        Number(shapeData["Point3Y"]) / 100,
        Number(shapeData["Point3Z"]) / 100,
        Number(shapeData["Point4X"]) / 100,
        Number(shapeData["Point4Y"]) / 100,
        Number(shapeData["Point4Z"]) / 100,
        Number(shapeData["A"]) / 100,
        Number(shapeData["B"]) / 100,
        Number(shapeData["C"]) / 100,
        Number(shapeData["D"]) / 100,
        Number(shapeData["E"]) / 100,
        material
      );
      shapeGroup.add(pyramid__);
      break;

    case "Box":
      let box = SHAPE.AddSixPlan2(
        Number(shapeData["Point1X"]) / 100,
        Number(shapeData["Point1Y"]) / 100,
        Number(shapeData["Point1Z"]) / 100,
        Number(shapeData["Point2X"]) / 100,
        Number(shapeData["Point2Y"]) / 100,
        Number(shapeData["Point2Z"]) / 100,
        Number(shapeData["Point3X"]) / 100,
        Number(shapeData["Point3Y"]) / 100,
        Number(shapeData["Point3Z"]) / 100,
        Number(shapeData["Point4X"]) / 100,
        Number(shapeData["Point4Y"]) / 100,
        Number(shapeData["Point4Z"]) / 100,
        Number(shapeData["A"]) / 100,
        Number(shapeData["B"]) / 100,
        Number(shapeData["C"]) / 100,
        Number(shapeData["D"]) / 100,
        Number(shapeData["E"]) / 100,
        material
      );
      shapeGroup.add(box);
      break;

      case "Box_支腿":
      let box_ = SHAPE.AddSixPlan2(
        Number(shapeData["Point1X"]) / 100,
        Number(shapeData["Point1Y"]) / 100,
        Number(shapeData["Point1Z"]) / 100,
        Number(shapeData["Point2X"]) / 100,
        Number(shapeData["Point2Y"]) / 100,
        Number(shapeData["Point2Z"]) / 100,
        Number(shapeData["Point3X"]) / 100,
        Number(shapeData["Point3Y"]) / 100,
        Number(shapeData["Point3Z"]) / 100,
        Number(shapeData["Point4X"]) / 100,
        Number(shapeData["Point4Y"]) / 100,
        Number(shapeData["Point4Z"]) / 100,
        Number(shapeData["A"]) / 100,
        Number(shapeData["B"]) / 100,
        Number(shapeData["C"]) / 100,
        Number(shapeData["D"]) / 100,
        Number(shapeData["E"]) / 100,
        material
      );
      shapeGroup.add(box_);
      break;


      case "Box_吊耳":
      let box__ = SHAPE.AddSixPlan2(
        Number(shapeData["Point1X"]) / 100,
        Number(shapeData["Point1Y"]) / 100,
        Number(shapeData["Point1Z"]) / 100,
        Number(shapeData["Point2X"]) / 100,
        Number(shapeData["Point2Y"]) / 100,
        Number(shapeData["Point2Z"]) / 100,
        Number(shapeData["Point3X"]) / 100,
        Number(shapeData["Point3Y"]) / 100,
        Number(shapeData["Point3Z"]) / 100,
        Number(shapeData["Point4X"]) / 100,
        Number(shapeData["Point4Y"]) / 100,
        Number(shapeData["Point4Z"]) / 100,
        Number(shapeData["A"]) / 100,
        Number(shapeData["B"]) / 100,
        Number(shapeData["C"]) / 100,
        Number(shapeData["D"]) / 100,
        Number(shapeData["E"]) / 100,
        material
      );
      shapeGroup.add(box__);
      break;


    default:
      break;
  }
}

let nozzleBox3Arr = ref([])
// 创建管口
function createNozzleModel(nozzleData) {
  let pos1Vector = new THREE.Vector3(
    Number(nozzleData["PipePortX"]),
    Number(nozzleData["PipePortY"]),
    Number(nozzleData["PipePortZ"])
  );
  let pos2Vector = new THREE.Vector3(
    Number(nozzleData["OtherPointX"]),
    Number(nozzleData["OtherPointY"]),
    Number(nozzleData["OtherPointZ"])
  );
  let nozzleLength = pos1Vector.distanceTo(pos2Vector);
  let nozzle = SHAPE.AddNozzel(
    Number(nozzleData["NPD"]) / 100,
    Number(nozzleData["PipePortX"]) / 100,
    Number(nozzleData["PipePortY"]) / 100,
    -Number(nozzleData["PipePortZ"]) / 100,
    Number(nozzleData["OtherPointX"]) / 100,
    Number(nozzleData["OtherPointY"]) / 100,
    -Number(nozzleData["OtherPointZ"]) / 100,
    Number(nozzleData["Preparation"]) / 100,
    (Number(nozzleLength) / 100) * 40,
    material
  );
  const color1 = new THREE.Color("#ff3653");
  //  let nozzleName = getSpriteMaterial(color1, nozzleData["NozzleName"])

  let nozzleName = new THREE.Sprite(
    getSpriteMaterial(color1, nozzleData["NozzleName"])
  );
  nozzleName.datas = nozzleData["NozzleName"];
  nozzleName.scale.set(4, 4, 1);
  nozzleName.position.x = Number(nozzleData["PipePortX"]) / 100;
  nozzleName.position.y =
    Number(nozzleData["PipePortY"]) >= 0
      ? Number(nozzleData["PipePortY"]) / 100
      : Number(nozzleData["PipePortY"]) / 100;
  nozzleName.position.z = -Number(nozzleData["PipePortZ"]) / 100;
  let a = new THREE.Vector3(
    Number(nozzleData["PipePortX"]) / 100,
    Number(nozzleData["PipePortY"]) / 100,
    -Number(nozzleData["PipePortZ"]) / 100
  );

  let b = new THREE.Vector3(
    Number(nozzleData["OtherPointX"]) / 100,
    Number(nozzleData["OtherPointY"]) / 100,
    -Number(nozzleData["OtherPointZ"]) / 100
  );

  let a_b = a.sub(b).normalize();
  nozzleName.quaternion.setFromUnitVectors(new THREE.Vector3(1, 0, 0), a_b);

  nozzleName.position.add(a_b.clone().multiplyScalar(2.5));

  nozzleName.position.add(
    new THREE.Vector3(0, -1, 0).normalize().clone().multiplyScalar(1)
  );

  clusterOf2D.push(nozzleName);
  nozzleGroup.add(nozzleName);
  
  nozzleGroup.add(nozzle);

  let nozzleBox3 = new THREE.Box3(new THREE.Vector3(), new THREE.Vector3());
  nozzleBox3.setFromObject(nozzle);
  nozzleBox3Arr.value.push({
    model: nozzle,
    box3: nozzleBox3,
    message:nozzleData,
  });
  // const nozzleBoxHelper = new THREE.BoxHelper(nozzle, 0xFFFFFF);

  // scene.add(nozzleBoxHelper)
}

function getSpriteMaterial(color, text = null) {
  let singleWidth = 20;
  let widthCan;
  if (text.length <= 5) {
    widthCan = 80;
  } else {
    widthCan = singleWidth * text.length;
  }

  const canvas = document.createElement("canvas");
  canvas.width = widthCan;
  canvas.height = widthCan;

  const cxt = canvas.getContext("2d");
  if (text !== null) {
    var x = 0; // 矩形左上角的x坐标
    var y = 0; // 矩形左上角的y坐标
    var width = widthCan; // 矩形的宽度
    var height = 40; // 矩形的高度
    var radius = 15; // 圆角的半径
    darwCan(cxt, x, y, width, height, radius);
    cxt.fillStyle = "skyblue";
    cxt.fill();

    cxt.font = "bold 25px Arial";
    cxt.textAlign = "center";
    cxt.textBaseline = "middle";
    cxt.fillStyle = "#fff";
    cxt.fillText(text, width / 2, height / 2);
  }

  const texture = new THREE.CanvasTexture(canvas);

  return new THREE.SpriteMaterial({ map: texture, toneMapped: false });
}

let darwCan = (cxt, x, y, width, height, radius) => {
  cxt.translate(x, y);
  cxt.beginPath(0);
  //从右下角顺时针绘制，弧度从0到1/2PI
  cxt.arc(width - radius, height - radius, radius, 0, Math.PI / 2);

  //矩形下边线
  cxt.lineTo(radius, height);

  //左下角圆弧，弧度从1/2PI到PI
  cxt.arc(radius, height - radius, radius, Math.PI / 2, Math.PI);

  //矩形左边线
  cxt.lineTo(0, radius);

  //左上角圆弧，弧度从PI到3/2PI
  cxt.arc(radius, radius, radius, Math.PI, (Math.PI * 3) / 2);

  //上边线
  cxt.lineTo(width - radius, 0);

  //右上角圆弧
  cxt.arc(width - radius, radius, radius, (Math.PI * 3) / 2, Math.PI * 2);

  //右边线
  cxt.lineTo(width, height - radius);
  cxt.closePath();
};

function onSelectMash(event) {
  const mouse = new THREE.Vector2();
  const { x, y, left, top, width, height } =
    render.domElement.getBoundingClientRect();

  mouse.x = ((event.clientX - x) / (width - left)) * 2 - 1;
  mouse.y = ((event.clientY - y) / (height - top)) * 2 - 1;
  raycaster.setFromCamera(mouse, camera);

  // 计算物体和射线的焦点

  const intersects = raycaster.intersectObjects(this.shapeGroup.children);

  if (intersects.length > 0) {
    const mesh = intersects[0].object;
    mesh.material.color = new THREE.Color(0xffbfff);
  }
}

let gui;
let controls;
let textureCube;
const manager = new THREE.LoadingManager();
textureCube = new THREE.CubeTextureLoader(manager)
  .setPath("threeImg/")
  .load(["px.jpg", "nx.jpg", "py.jpg", "ny.jpg", "pz.jpg", "nz.jpg"]);
textureCube.minFilter = THREE.LinearFilter;

manager.onProgress = function (url, itemsLoaded, itemsTotal) {
  if (itemsLoaded == itemsTotal) {
    emit("initImgFinsh", true);
  }
};
const css3Renderer = new CSS2DRenderer();
// 定义生命周期函数
onMounted(async () => {
  setTimeout(() => {
    if (gui) {
      gui.destroy();
      gui = null;
    }

    material.envMap = textureCube;

    gui = new dat.GUI();
    let cameraGroupGui = gui.addFolder("视图");
    let shapeGroupGui = gui.addFolder("基本体");
    let masterialGroupGui = gui.addFolder("预焊件");

    let params = {
      color: "#eee",
      visible: true,
      opacity: 1,
      OrthographicCamera: true,
      shapeOpacity: 1,
      shapeColor: "#eee",
      recoverShapeColor: () => {
        shapeGroup.children.forEach((v) => {
          if (v.type == "Mesh") {
            v.material.color = new THREE.Color("#d84c21");
          }
        });
      },
      recoverCylinderColor: () => {
        cylinderMeshcolorBoxArr.forEach((v) => {
          v.material.color = new THREE.Color("#bf0000");
        });
      },
    };
    cameraGroupGui
      .add(params, "OrthographicCamera")
      .name("正交/透视视图切换")
      .onChange((data) => {
        if (showFullIcon.value) {
          if (data) {
            cameraType.value = "正交视图";
            let OrthographicCamera = new THREE.OrthographicCamera(
              -props.canvasWidth / 2,
              props.canvasWidth / 2,
              props.canvasHeight / 2,
              -props.canvasHeight / 2,
              -800,
              800
            );
            OrthographicCamera.position.set(72, 109, 86); //设置相机在三维坐标中的位置
            OrthographicCamera.lookAt(0, 0, 0); //设置观察方向
            OrthographicCamera.updateProjectionMatrix();
            OrthographicCamera.zoom = 2;
            camera = OrthographicCamera;
            controls.object = OrthographicCamera;
          } else {
            cameraType.value = "透视视图";
            let PerspectiveCamera = new THREE.PerspectiveCamera(
              75,
              props.canvasWidth / props.canvasHeight,
              0.1,
              10000
            );
            PerspectiveCamera.position.set(72, 109, 86); //设置相机在三维坐标中的位置
            PerspectiveCamera.lookAt(0, 0, 0); //设置观察方向
            PerspectiveCamera.updateProjectionMatrix();
            PerspectiveCamera.zoom = 2;
            camera = PerspectiveCamera;
            controls.object = PerspectiveCamera;
          }
        } else {
          setTimeout(() => {
            if (data) {
              cameraType.value = "正交视图";
              let OrthographicCamera = new THREE.OrthographicCamera(
                -document.body.clientWidth / 2,
                document.body.clientWidth / 2,
                document.body.clientHeight / 2,
                -document.body.clientHeight / 2,
                -800,
                800
              );
              OrthographicCamera.position.set(72, 109, 86); //设置相机在三维坐标中的位置
              OrthographicCamera.lookAt(0, 0, 0); //设置观察方向
              OrthographicCamera.updateProjectionMatrix();
              OrthographicCamera.zoom = 2;
              camera = OrthographicCamera;
              controls.object = OrthographicCamera;
            } else {
              cameraType.value = "透视视图";
              let PerspectiveCamera = new THREE.PerspectiveCamera(
                75,
                document.body.clientWidth / document.body.clientHeight,
                0.1,
                10000
              );
              PerspectiveCamera.position.set(72, 109, 86); //设置相机在三维坐标中的位置
              PerspectiveCamera.lookAt(0, 0, 0); //设置观察方向
              PerspectiveCamera.updateProjectionMatrix();
              PerspectiveCamera.zoom = 2;
              camera = PerspectiveCamera;
              controls.object = PerspectiveCamera;
            }
          }, 0);
          setTimeout(() => {
            document.querySelector(".model").style.position = "fixed";
          }, 10);
        }
      });

    masterialGroupGui
      .addColor(params, "color")
      .name("预焊件颜色")
      .onChange(() => {
        cylinderMeshcolorBoxArr.forEach((v) => {
          v.material.color = new THREE.Color(params.color);
        });
      });

    masterialGroupGui
      .add(params, "opacity")
      .name("预焊件透明度")
      .max(1)
      .min(0)
      .step(0.1)

      .onChange((data) => {
        cylinderMeshcolorBoxArr.forEach((v) => {
          v.material.opacity = params.opacity;
          v.material.transparent = true;
        });
      });

    masterialGroupGui
      .add(params, "recoverCylinderColor")
      .name("恢复预焊件初始颜色");

    shapeGroupGui
      .add(params, "shapeOpacity")
      .max(1)
      .min(0)
      .step(0.1)
      .name("基本体透明度")
      .onChange((data) => {
        shapeGroup.children.forEach((v) => {
          if (v.type == "Mesh") {
            v.material.opacity = data;
            v.material.transparent = true;
          }
        });
      });
    shapeGroupGui
      .addColor(params, "color")
      .name("基本体颜色")
      .onChange((data) => {
        shapeGroup.children.forEach((v) => {
          if (v.type == "Mesh") {
            v.material.color = new THREE.Color(params.color);
          }
        });
      });
    shapeGroupGui.add(params, "recoverShapeColor").name("恢复基本体初始颜色");

    document.querySelector(".box_model").appendChild(gui.domElement, document);
    gui.domElement.style.position = "absolute";
    gui.domElement.style.right = "-5px";
    gui.domElement.style.top = "0";
    gui.domElement.style.zIndex = "99";
  }, 3000);

  css3Renderer.setSize(props.canvasWidth, props.canvasHeight);

  css3Renderer.domElement.style.position = "absolute";
  css3Renderer.domElement.style.top = "0px";

  css3Renderer.domElement.style.pointerEvents = "none";
  webglRef.value.appendChild(css3Renderer.domElement);

  webglRef.value.appendChild(render.domElement);
  camera = new THREE.OrthographicCamera(
    -props.canvasWidth / 2,
    props.canvasWidth / 2,
    props.canvasHeight / 2,
    -props.canvasHeight / 2,
    0.001,
    80000
  );
  // camera.position.set(72, 109, 86); //设置相机在三维坐标中的位置
  camera.lookAt(0, 0, 0); //设置观察方向

  // controls.enableDamping = true;
  renderFn();
  camera.left = -props.canvasWidth / 2;
  camera.right = props.canvasWidth / 2;
  camera.top = props.canvasHeight / 2;
  camera.bottom = -props.canvasHeight / 2;
  camera.position.set(172, 109, 186);
  camera.zoom = 5;

  camera.aspect = props.canvasWidth / props.canvasHeight;
  camera.updateProjectionMatrix();
  render.setSize(props.canvasWidth, props.canvasHeight);
  controls = new OrbitControls(camera, render.domElement);

  shapeModel();
  nozzleModel();
  window.addEventListener("click", clickFn);
});

// 手动懒加载模型
let ayncFn = (data) => {
  return new Promise((res) => {
    CreatepreWeldedModel(data, res);
  });
};

// 射线检测
const raycaster = new THREE.Raycaster();

const pointer = new THREE.Vector2();
let materialChange = new THREE.MeshLambertMaterial({
  color: "red",
  wireframe: true,
  transparent: true,
});

let clickFn = (event) => {
  let container = document.querySelector(".canvas");
  if (container) {
    let getBoundingClientRect = container.getBoundingClientRect();

    pointer.x =
      ((event.clientX - getBoundingClientRect.left) / container.offsetWidth) *
        2 -
      1;
    pointer.y =
      -((event.clientY - getBoundingClientRect.top) / container.offsetHeight) *
        2 +
      1;

    raycaster.setFromCamera(pointer, camera);

    let newBoxArr = raycaster.intersectObjects(clusterOf2D);

    if (newBoxArr.length > 0) {
      EquipmentStore.nozzleName = newBoxArr[0]?.object?.datas;
    }
  }
};

// 扩展功能  鼠标移动判断物体位置  可能会用到
// let mouseupFn = () => {
//   if (clusterOf2D.value.length > 0) {
//             clusterOf2D.value.forEach((c) => {
//                 raycasterCollsionDetect(c)
//             })
//         }
// }

// 扩展功能  鼠标移动判断物体位置  可能会用到
// window.addEventListener("mouseup", mouseupFn);

let requestAnimationFrameId;
let renderFn = () => {
  render.render(scene, camera); //渲染操作
  css3Renderer.render(scene, camera);
  TWEEN.update();
  camera.updateProjectionMatrix();

  requestAnimationFrameId = requestAnimationFrame(renderFn);
};

let clusterOf2D = [];

let raycasterCollsionDetect = (wavesLabel) => {
  const labelPosition = wavesLabel.position.clone();

  const labelDistance = labelPosition.distanceTo(camera.position);

  labelPosition.project(camera);
  raycaster.setFromCamera(labelPosition, camera);
  let model = scene.children.filter((v) => {
    return v instanceof THREE.Group;
  });

  //过滤出模型
  if (model.length > 0) {
    const intersects = raycaster.intersectObjects(model[1].children);

    if (intersects.length == 0) {
      // 如果标签没有被model遮挡，应该全部显示
      wavesLabel.element.classList.add("visible");
    } else {
      const minDistance = intersects[0].distance;
      if (minDistance < labelDistance) {
        // 如果模型到相机的距离小于标签到相机的距离，说明光线射线先经过模型
        // 表面此时标签其实在模型的后面，应该被遮挡而看不见
        wavesLabel.element.classList.remove("visible");
        wavesLabel.element.classList.add("hidden");
      } else {
        wavesLabel.element.classList.add("visible");
        wavesLabel.element.classList.remove("hidden");
      }
    }
  }
};

// 卸载前执行
onBeforeUnmount(() => {
  camera.position.set(72, 109, 86);
  camera.lookAt(0, 0, 0);
  scene.remove(shapeGroup);
  scene.remove(nozzleGroup);
  scene.remove(preWeldedGroup);
  scene.remove(PlantformPreWeldedPartGroup);
  render.dispose();

  cancelAnimationFrame(requestAnimationFrameId);

  gui.close();
});

watch(props, () => {
  //由父组件传过来的宽高值，绘制画布

  shapeModel();
  nozzleModel();
});

let circleBoxGroup = new THREE.Group();
let createCircleBox = () => {
  scene.remove(circleBoxGroup);
  circleBoxGroup.children.splice(0, circleBoxGroup.children.length);

  circleBoxGroup.add(circleBox({}));
  scene.add(circleBoxGroup);
  render.render(scene, camera);
  webglRef.value.appendChild(render.domElement);
};
let boxArr = [];
let preWeldedGroup = new THREE.Group();

let CreatepreWeldedModel = async (data, res) => {
  preWeldedGroup.children.splice(0, preWeldedGroup.children.length);

  let materialXD = new THREE.MeshStandardMaterial({
    color: new THREE.Color("#bf0000"),
    roughness: 0.2,
    metalness: 0.8,
    envMap: textureCube,
    side: THREE.DoubleSide,
  });
  let materialXH = new THREE.MeshStandardMaterial({
    color: new THREE.Color("#bf0000"),
    envMap: textureCube,
    roughness: 0.2,
    metalness: 0.8,

    side: THREE.DoubleSide,
  });

  let newGroups = new THREE.Group();

  data.forEach((v) => {
    v.PreWeldPoints.forEach((item) => {
      newGroups.add(
        preWeldedModel({
          diam: v.SuppLugDiam / 100,
          E: v.E / 100,
          T: v.T / 100,
          p0: new THREE.Vector3(item.X0 / 100, item.Y0 / 100, item.Z0 / 100),
          p1: new THREE.Vector3(item.X1 / 100, item.Y1 / 100, item.Z1 / 100),
          material: materialXD,
          data: v,
        })
      );
    });
    if (v.TBLX.includes("NGEN2")) {
      v.PreWeldPoints.forEach((item) => {
        newGroups.add(
          reinforcePad({
            innerRadius: v.CylinderDiam / 2 / 100,
            E: v.E / 100,
            T: v.T / 100,
            p0: new THREE.Vector3(item.X0 / 100, item.Y0 / 100, item.Z0 / 100),
            p1: new THREE.Vector3(item.X1 / 100, item.Y1 / 100, item.Z1 / 100),
            material: materialXH,
            data: v,
          })
        );
      });
    }
    if (v.TBLX.includes("NGEN4")) {
      v.PreWeldPoints.forEach((item) => {
        newGroups.add(
          reinforcePad2({
            innerRadius: v.CylinderDiam / 2 / 100,
            E: v.E / 100,
            T: v.T / 100,
            p0: new THREE.Vector3(item.X0 / 100, item.Y0 / 100, item.Z0 / 100),
            p1: new THREE.Vector3(item.X1 / 100, item.Y1 / 100, item.Z1 / 100),
            material: materialXH,
            N4CylinderY: v.N4CylinderY / 100,
            data: v,
          })
        );
      });
    }

    if (!v.IsDataCorrect) {
      messageArr.value.push(v);
    }
    preWeldedGroup.add(newGroups);
  });

  // 使用宏事件  将模型添加到场景中并且使这个线程最后执行
  setTimeout(() => {
    scene.add(preWeldedGroup);
    // render.render(scene, camera);
    // webglRef.value.appendChild(render.domElement);
    res(true);
    emit("initFinsh", true);
    messageArr.value.length > 0
      ? ElNotification({
          title: "提示！！",
          type: "warning",
          dangerouslyUseHTMLString: true,
          message: `${messageArr.value
            .map((v, index) => {
              return `<p style='margin-bottom:10px;font-weight:700'>${
                index + +1
              } . <span style='font-weight:700'> ${
                v.TBLX
              }</span> 数据有误，请检查</p>`;
            })
            .join(" ")}`,
        })
      : "";
  }, 20);
};

let messageArr = ref([]);

let reinforcePad2 = ({
  innerRadius = 20,
  E,
  T,
  p0,
  p1,
  material,
  N4CylinderY = 7,
}) => {
  const outerRadius = innerRadius + T;
  const thetaStart = Math.PI / 2 - E / innerRadius / 2;
  const thetaLength = E / innerRadius;
  const shape = new THREE.Shape(); // Move to the starting point
  shape.moveTo(
    outerRadius * Math.cos(thetaStart),
    outerRadius * Math.sin(thetaStart)
  ); // Draw the outer arc

  shape.absarc(0, 0, outerRadius, thetaStart, thetaStart + thetaLength, false); // Line to the inner arc's end point

  shape.lineTo(
    innerRadius * Math.cos(thetaStart + thetaLength),
    innerRadius * Math.sin(thetaStart + thetaLength)
  ); // Draw the inner arc

  shape.absarc(0, 0, innerRadius, thetaStart + thetaLength, thetaStart, true); // Close the path

  shape.lineTo(
    outerRadius * Math.cos(thetaStart),
    outerRadius * Math.sin(thetaStart)
  );

  const extrudeSettings = {
    curveSegments: 100,
    steps: 1,
    depth: E, // 拉伸的深度
    bevelEnabled: false,
  };

  const extrudeGeometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
  extrudeGeometry.translate(0, 0, -E / 2);

  extrudeGeometry.rotateY(-Math.PI / 2);

  const tempP = p0.clone();

  const ringMesh = new THREE.Mesh(extrudeGeometry, material);
  ringMesh.position.set(p0.x, N4CylinderY, 0);

  let ANg = new THREE.Vector3(0, tempP.y, tempP.z);
  let XL = ANg.sub(new THREE.Vector3(0, N4CylinderY, 0)).normalize();

  let quaternion = new THREE.Quaternion();

  quaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), XL);
  ringMesh.quaternion.multiply(quaternion);

  const cyl = new THREE.CylinderGeometry(E / 2, E / 2, T, 12);
  cyl.translate(0, innerRadius, 0);
  const meshCyl = new THREE.Mesh(cyl, material);
  meshCyl.position.set(p0.x, N4CylinderY, 0);
  meshCyl.quaternion.multiply(quaternion);

  let Group = new THREE.Group();

  // Group.add(ringMesh);
  // Group.add(meshCyl);

  meshCyl.updateMatrix();
  ringMesh.updateMatrix();
  const bspCyl = CSG.fromMesh(meshCyl);
  const bspRing = CSG.fromMesh(ringMesh);
  const bspResult = bspRing.intersect(bspCyl);

  const meshResult = CSG.toMesh(bspResult, meshCyl.matrixWorld, material);

  Group.add(meshResult);

  Group.userData.type = "JIAQIANGBAN";

  return Group;
};

let reinforcePad = ({ innerRadius = 20, E, T, p0, p1, material }) => {
  // const innerRadius = 2.37
  const outerRadius = innerRadius + T;
  const thetaStart = Math.PI / 2 - E / innerRadius / 2;
  const thetaLength = E / innerRadius;
  const shape = new THREE.Shape(); // Move to the starting point
  shape.moveTo(
    outerRadius * Math.cos(thetaStart),
    outerRadius * Math.sin(thetaStart)
  ); // Draw the outer arc

  shape.absarc(0, 0, outerRadius, thetaStart, thetaStart + thetaLength, false); // Line to the inner arc's end point

  shape.lineTo(
    innerRadius * Math.cos(thetaStart + thetaLength),
    innerRadius * Math.sin(thetaStart + thetaLength)
  ); // Draw the inner arc

  shape.absarc(0, 0, innerRadius, thetaStart + thetaLength, thetaStart, true); // Close the path

  shape.lineTo(
    outerRadius * Math.cos(thetaStart),
    outerRadius * Math.sin(thetaStart)
  );

  const extrudeSettings = {
    curveSegments: 100,
    steps: 1,
    depth: E, // 拉伸的深度
    bevelEnabled: false,
  };

  const extrudeGeometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
  extrudeGeometry.translate(0, 0, -E / 2); //将贴板向-Y方向移动贴板宽度一半
  extrudeGeometry.rotateX(-Math.PI / 2); //将贴板绕X轴旋转-90度，到Z轴的负半轴
  extrudeGeometry.rotateY(-Math.PI / 2); //将贴板绕X轴旋转-90度，到Z轴的负半轴
  extrudeGeometry.translate(0, p0.y, 0); //将贴板高度调整与p0点相同

  const tempP = p0.clone();
  tempP.y = 0;

  const ringMesh = new THREE.Mesh(extrudeGeometry, material);
  let quaternion = new THREE.Quaternion();

  quaternion.setFromUnitVectors(
    new THREE.Vector3(1, 0, 0),
    tempP.sub(new THREE.Vector3(0, 0, 0)).normalize()
  );
  ringMesh.quaternion.multiply(quaternion);
  const cyl = new THREE.CylinderGeometry(E / 2, E / 2, T, 12);
  cyl.rotateZ(Math.PI / 2);
  const meshCyl = new THREE.Mesh(cyl, material);
  meshCyl.position.copy(p0);
  meshCyl.quaternion.multiply(quaternion);

  let Group = new THREE.Group();
  cylinderMeshcolorBoxArr.push(ringMesh);

  cylinderMeshcolorBoxArr.push(meshCyl);
  Group.add(ringMesh);
  Group.add(meshCyl);

  // meshCyl.updateMatrix();
  // ringMesh.updateMatrix();
  // const bspCyl = CSG.fromMesh(meshCyl);
  // const bspRing = CSG.fromMesh(ringMesh);
  // const bspResult = bspRing.intersect(bspCyl);

  // const meshResult = CSG.toMesh(bspResult, meshCyl.matrixWorld, material);

  // Group.add(meshResult);

  Group.userData.type = "JIAQIANGBAN";

  return Group;
};

let preWeldedModel = ({ diam, E, T, p0, p1, material, data }) => {
  return complexModelFactory({ diam, E, T, p0, p1, material, data });
};

let circleHoleGroup = new THREE.Group();
let createCircleHole = () => {
  scene.remove(circleHoleGroup);
  circleHoleGroup.children.splice(0, circleHoleGroup.children.length);

  circleHoleGroup.add(
    circleHole({
      innerRadius: 5,
      outerRadius: 6,
      thetastart: 0,
      thetaLength: (Math.PI / 180) * 30,
    })
  );

  scene.add(circleHoleGroup);
  render.render(scene, camera);
  webglRef.value.appendChild(render.domElement);
};
let circleHole = ({
  innerRadius = 5,
  outerRadius = 6,
  thetastart = 0,
  thetaLength = (Math.PI / 180) * 30,
  Bodydepth = 4,
}) => {
  let bigCircle = new THREE.Shape();
  bigCircle.moveTo(
    outerRadius * Math.cos(thetastart),
    outerRadius * Math.sin(thetastart)
  );

  bigCircle.absarc(
    0,
    0,
    outerRadius,
    thetastart,
    thetastart + thetaLength,
    false
  );
  bigCircle.lineTo(
    innerRadius * Math.cos(thetastart + thetaLength),
    innerRadius * Math.sin(thetastart + thetaLength)
  );
  bigCircle.absarc(
    0,
    0,
    innerRadius,
    thetastart + thetaLength,
    thetastart,
    true
  );
  bigCircle.lineTo(
    outerRadius * Math.cos(thetastart),
    outerRadius * Math.sin(thetastart)
  );

  let tube = new THREE.ExtrudeGeometry(bigCircle, {
    depth: Bodydepth,
    bevelEnabled: false,
    curveSegments: 100,
    steps: 1000,
  });

  // let material = new THREE.MeshStandardMaterial({
  //   color: 0x00bfff,
  //   transparent: true,
  //   opacity: 0.5,
  //   side: THREE.DoubleSide,
  // });
  let material = new THREE.MeshStandardMaterial({
    color: new THREE.Color("#454649"),
    roughness: 0.2,
    metalness: 1,

    side: THREE.DoubleSide,
  });

  let mesh = new THREE.Mesh(tube, material);
  let Group = new THREE.Group();
  Group.add(mesh);

  return Group;
};

// 创建圆形底板
let circleBox = ({ bigRadius = 7, depth = 1, height = 15 }) => {
  let bigCircle = new THREE.Shape();
  bigCircle.moveTo(bigRadius * Math.cos(0), bigRadius * Math.sin(0));

  bigCircle.absarc(0, 0, bigRadius, 0, Math.PI, false);

  bigCircle.lineTo(bigRadius * Math.cos(Math.PI), -height);
  bigCircle.lineTo(bigRadius, -height);
  bigCircle.lineTo(bigRadius * Math.cos(0), bigRadius * Math.sin(0));
  let smallCircle = new THREE.Shape();

  smallCircle.arc(0, bigRadius / 3, bigRadius / 3, 0, Math.PI * 2, false);
  bigCircle.holes.push(smallCircle);
  let tube = new THREE.ExtrudeGeometry(bigCircle, {
    depth: depth,
    bevelEnabled: false,
    curveSegments: 100,
    steps: 1000,
  });

  // let material = new THREE.MeshStandardMaterial({
  //   color: 0x00bfff,
  //   transparent: true,
  //   opacity: 0.5,
  //   side: THREE.DoubleSide,
  // });
  let material = new THREE.MeshStandardMaterial({
    color: new THREE.Color("#454649"),
    roughness: 0.2,
    metalness: 1,

    side: THREE.DoubleSide,
  });

  let mesh = new THREE.Mesh(tube, material);
  let Group = new THREE.Group();
  Group.add(mesh);

  return Group;
};

// 创建圆柱体
let createCylinder = ({ radius, height, detail }) => {
  return new THREE.CylinderGeometry(radius, radius, height, detail);
};

// 创建正方体
let createBox = ({ width, height, depth }) => {
  return new THREE.BoxGeometry(width, height, depth);
};

// Mesh
let createMesh = (geometry, material) => {
  return new THREE.Mesh(geometry, material);
};

// 旋转到合适的角度
let applyQuaternionToGroup = (group, fromVector, toVector) => {
  group.quaternion.setFromUnitVectors(fromVector, toVector.normalize());
};

let cylinderMeshcolorBoxArr = [];
let boxMeshcolorArr = [];
let complexModelFactory = ({ diam, E, T, p0, p1, material, data }) => {
  const group = new THREE.Group();
  const length = p1.clone().sub(p0).length();
  const cylinderGeometry = createCylinder({
    radius: diam / 2,
    height: length,
    detail: 32,
  });
  const cylinderMesh = createMesh(cylinderGeometry, material);
  const boxGeometry = createBox({ width: E, height: T, depth: E });
  const boxMesh = createMesh(boxGeometry, material);

  cylinderMesh.position.set(0, -length / 2 + T, 0);
  boxMesh.position.set(0, T, 0);
  cylinderMesh.userData = { ...data, types: "YUANZHU" };

  boxMesh.userData = { ...data };
  group.add(cylinderMesh, boxMesh);
  cylinderMeshcolorBoxArr.push(cylinderMesh);
  boxMeshcolorArr.push(boxMesh);
  group.rotateX(-Math.PI / 2);
  group.translateY(length);
  group.userData.type = "modelGroup";
  const newGroupModel = new THREE.Group();
  newGroupModel.add(group);

  newGroupModel.position.copy(p0);
  applyQuaternionToGroup(
    newGroupModel,
    new THREE.Vector3(0, 0, -1),
    p1.clone().sub(p0)
  );

  boxArr.push(newGroupModel);

  newGroupModel.userData.type = "holeBox";

  return newGroupModel;
};

let showModel = ref(false);
let newMessageArr = ref([]);
watch(
  () => props.CalPipeSuppPreWeld,
  async () => {
    if (props.CalPipeSuppPreWeld[0] !== "初始数据") {
      let data = Array.isArray(props.CalPipeSuppPreWeld)
        ? props.CalPipeSuppPreWeld
        : [];
      let copyData = JSON.parse(JSON.stringify(data));

      // 深拷贝数据 防止修改源数据
      let arr = [copyData];

      // 懒加载模型
      for (let i = 0; i < arr.length; i++) {
        await ayncFn(arr[i]);
      }
    }
  },
  { immediate: true }
);

let loader = new GLTFLoader();
let ModelObj = {};


let checkClose = () => {
  checkCloseMessage.value = []
  let nozzleBox3Arrlength  = nozzleBox3Arr.value.length
  let preWeldedPartBox3Arrlength = preWeldedPartBox3Arr.value.length
  if(!nozzleBox3Arrlength||!preWeldedPartBox3Arrlength){
    ElMessage({
      type:'error',
      message:'没有需要检测的模型！'
    })
    return
  }
  if(nozzleBox3Arrlength > preWeldedPartBox3Arrlength ){
    checkCloseFn(nozzleBox3Arr.value,preWeldedPartBox3Arr.value)
  }else{
    checkCloseFn(preWeldedPartBox3Arr.value,nozzleBox3Arr.value)
  }
}


let checkCloseMessage = ref([])
let checkCloseFn = (a,b) => {
   a.forEach(v=>{
   
      b.forEach(i=> {
        
        if(v.box3.intersectsBox(i.box3)){
          const preWeldedPartBox3Helper1 = new THREE.BoxHelper(v.model, 0xFFFFFF);
          const preWeldedPartBox3Helper2 = new THREE.BoxHelper(i.model, new THREE.Color("#ccc"));
          scene.add(preWeldedPartBox3Helper1);
          scene.add(preWeldedPartBox3Helper2);
          
          checkCloseMessage.value.push({
            a:v.message,
            b:i.message
          })
        }

      })
   })

   if(checkCloseMessage.value.length>0){
    console.log(checkCloseMessage.value)
    ElNotification({
       title: '碰撞检测结果',
       dangerouslyUseHTMLString: true,
       duration:0,
       onClose:()=>{
       let arr = []
        scene.children.forEach(v=>{
          v.type==="BoxHelper"?(
           arr.push(v)
          ):[]
          
        })
        scene.remove(...arr)
        
       },
       message: `${(
        (checkCloseMessage.value.map((v,index)=>{
          return `<div class="cusDiv_">
          ${index + 1}.管口<span style='color:red'>${v.b.NozzleName}</span>与 高度:${v.a.EL / 100} 角度:${v.a.Degree} 的${v.a.Type}发生碰撞</div>`
        })).toString().replace(/,<div class="cusDiv_">/g, '<div class="cusDiv_">')
      )}`,
       position: 'top-left',
  })
   }
}



let ThreeModelGet = (data) => {
  return new Promise((res, rej) => {
    let obj = {};
    let numArr = [];
    data.forEach((v, i) => {
      loader.load(
        `model/${v}.glb`,
        (gltf) => {
          gltf.scene.children.forEach((v) => {
            v.material.envMap = textureCube;
            v.material.side = THREE.DoubleSide;
            v.material.color = new THREE.Color("#6e02cf");
            v.material.roughness = 0.2;
            v.material.metalness = 0.8;
          });
          obj[v] = gltf.scene;
        },

        (loadEvent) => {
          numArr.push(i);
          if (numArr.length == data.length) {
            setTimeout(() => {
              res(obj);
            }, 500);
          }
        }
      );
    });
  });
};

// 过滤需要的模型
let loadModelFn = async (data) => {
  return new Promise(async (res) => {
    let dataModel = [...new Set(data.map((v) => v.Type))];
    let arr = hasModel.filter((item) => {
      return dataModel.includes(item);
    });

    res(await ThreeModelGet(arr));
  });
};

let PlantformPreWeldedPartGroup;
PlantformPreWeldedPartGroup = new THREE.Group();
let loadPlantformPreWeldedPartModel = (data) => {
  let materialXD = new THREE.MeshStandardMaterial({
    color: new THREE.Color("#6e02cf"),
    roughness: 0.2,
    metalness: 0.8,
    envMap: textureCube,
    side: THREE.DoubleSide,
  });
  PlantformPreWeldedPartGroup.children.splice(
    0,
    preWeldedGroup.children.length
  );

  // 从数据中过滤xze CZE TZE DZE 等模型数据
  let XZEData = JSON.parse(JSON.stringify(data)).filter((v) =>
    v.Type.includes("XZE")
  );
  let CZEData = JSON.parse(JSON.stringify(data)).filter((v) =>
    v.Type.includes("CZE")
  );

  let TZE1Data = JSON.parse(JSON.stringify(data)).filter((v) =>
    v.Type.includes("TZE")
  );

  let DZEData = JSON.parse(JSON.stringify(data)).filter((v) =>
    v.Type.includes("DZE")
  );

  DZEData.forEach((v) => {
    if (hasModel.includes(v.Type)) {
      PlantformPreWeldedPartGroup.add(loadDZEModelSingle(v));
    }
  });

  XZEData.forEach((v) => {
    if (hasModel.includes(v.Type)) {
      PlantformPreWeldedPartGroup.add(loadPlantformPreWeldedPartModelSingle(v));
      PlantformPreWeldedPartGroup.add(
        reinforcePadPlantformPreWeldedPartModel({
          Type: v.Type,
          Degree: v.Degree,
          EL: v.EL / 100,
          innerRadius: v.L2 / 100,
          T: hasModelObj[v.Type].T,
          E: hasModelObj[v.Type].E,
          D: hasModelObj[v.Type].D,
          material: materialXD,
        })
      );
    }
  });
  CZEData.forEach((v) => {
    if (hasModel.includes(v.Type)) {
      PlantformPreWeldedPartGroup.add(loadPlantformPreWeldedPartModelSingle(v));
      PlantformPreWeldedPartGroup.add(
        reinforcePadPlantformPreWeldedPartModel2({
          Type: v.Type,
          Degree: v.Degree,
          EL: v.EL / 100,
          innerRadius: v.L2 / 100,
          T: hasModelObj[v.Type].T,
          E: hasModelObj[v.Type].E,
          E2: hasModelObj[v.Type].E2,
          D: hasModelObj[v.Type].D,
          H: hasModelObj[v.Type].H,
          material: materialXD,
        })
      );
    }
  });

  TZE1Data.forEach((v) => {
    if (hasModel.includes(v.Type)) {
      PlantformPreWeldedPartGroup.add(loadPlantformPreWeldedPartModelSingle(v));
      PlantformPreWeldedPartGroup.add(
        reinforcePadPlantformPreWeldedPartModelTZE({
          Type: v.Type,
          Degree: v.Degree,
          EL: v.EL / 100,
          innerRadius: v.L2 / 100,
          T: hasModelObj[v.Type].T,
          E: hasModelObj[v.Type].E,
          D: hasModelObj[v.Type].D,
          material: materialXD,
        })
      );
    }
  });

  scene.add(PlantformPreWeldedPartGroup);
};

let reinforcePadPlantformPreWeldedPartModelTZE = ({
  Type,
  innerRadius = 20,
  D,
  T,
  E,
  material,
  EL,
  Degree,
}) => {
  const outerRadius = innerRadius + T;
  const thetaStart = Math.PI / 2 - D / innerRadius / 2;
  const thetaLength = D / innerRadius;
  const shape = new THREE.Shape(); // Move to the starting point
  shape.moveTo(
    outerRadius * Math.cos(thetaStart),
    outerRadius * Math.sin(thetaStart)
  ); // Draw the outer arc

  shape.absarc(0, 0, outerRadius, thetaStart, thetaStart + thetaLength, false); // Line to the inner arc's end point

  shape.lineTo(
    innerRadius * Math.cos(thetaStart + thetaLength),
    innerRadius * Math.sin(thetaStart + thetaLength)
  );
  shape.absarc(0, 0, innerRadius, thetaStart + thetaLength, thetaStart, true); // Close the path

  shape.lineTo(
    outerRadius * Math.cos(thetaStart),
    outerRadius * Math.sin(thetaStart)
  );

  const extrudeSettings = {
    curveSegments: 100,
    steps: 1,
    depth: E,
    bevelEnabled: false,
  };

  const extrudeGeometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);

  extrudeGeometry.rotateX(-Math.PI / 2);
  extrudeGeometry.translate(0, -(E / 2), 0);

  const ringMesh = new THREE.Mesh(extrudeGeometry, material);

  ringMesh.position.set(0, EL, 0);

  let Group = new THREE.Group();
  Group.add(ringMesh);
  Group.quaternion.setFromAxisAngle(
    new THREE.Vector3(0, 1, 0),
    (-Math.PI / 180) * Degree
  );

  Group.userData.type = "JIAQIANGBAN";

  return Group;
};

let reinforcePadPlantformPreWeldedPartModel = ({
  Type,
  innerRadius = 20,
  D,
  T,
  E,
  material,
  EL,
  Degree,
}) => {
  const outerRadius = innerRadius + T;
  const thetaStart = Math.PI / 2 - D / innerRadius / 2;
  const thetaLength = D / innerRadius;
  const shape = new THREE.Shape(); // Move to the starting point
  shape.moveTo(
    outerRadius * Math.cos(thetaStart),
    outerRadius * Math.sin(thetaStart)
  ); // Draw the outer arc

  shape.absarc(0, 0, outerRadius, thetaStart, thetaStart + thetaLength, false); // Line to the inner arc's end point

  shape.lineTo(
    innerRadius * Math.cos(thetaStart + thetaLength),
    innerRadius * Math.sin(thetaStart + thetaLength)
  );
  shape.absarc(0, 0, innerRadius, thetaStart + thetaLength, thetaStart, true); // Close the path

  shape.lineTo(
    outerRadius * Math.cos(thetaStart),
    outerRadius * Math.sin(thetaStart)
  );

  const extrudeSettings = {
    curveSegments: 100,
    steps: 1,
    depth: E,
    bevelEnabled: false,
  };

  const extrudeGeometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
  if (!Type.includes("s")) {
    extrudeGeometry.translate(0.5, 0, -(E / 2));
    extrudeGeometry.rotateX(-Math.PI / 2);
    extrudeGeometry.translate(0, -(E / 2) - 0.1, 0);

    const ringMesh = new THREE.Mesh(extrudeGeometry, material);

    ringMesh.position.set(0, EL, 0);

    let Group = new THREE.Group();
    Group.add(ringMesh);
    Group.quaternion.setFromAxisAngle(
      new THREE.Vector3(0, 1, 0),
      (-Math.PI / 180) * Degree
    );

    Group.userData.type = "JIAQIANGBAN";

    return Group;
  } else if (Type.includes("s")) {
    extrudeGeometry.translate(-0.5, 0, -(E / 2));
    extrudeGeometry.rotateX(-Math.PI / 2);
    extrudeGeometry.translate(0, -(E / 2) - 0.1, 0);

    const ringMesh = new THREE.Mesh(extrudeGeometry, material);

    ringMesh.position.set(0, EL, 0);

    let Group = new THREE.Group();
    Group.add(ringMesh);
    Group.quaternion.setFromAxisAngle(
      new THREE.Vector3(0, 1, 0),
      (-Math.PI / 180) * Degree
    );

    Group.userData.type = "JIAQIANGBAN";

    return Group;
  }
};

let reinforcePadPlantformPreWeldedPartModel2 = ({
  Type,
  innerRadius = 20,
  D,
  T,
  E,
  E2,
  H,
  material,
  EL,
  Degree,
}) => {
  const outerRadius = innerRadius + T;
  const thetaStart = Math.PI / 2 - D / innerRadius / 2;
  const thetaLength = D / innerRadius;
  const shape = new THREE.Shape(); // Move to the starting point
  shape.moveTo(
    outerRadius * Math.cos(thetaStart),
    outerRadius * Math.sin(thetaStart)
  ); // Draw the outer arc

  shape.absarc(0, 0, outerRadius, thetaStart, thetaStart + thetaLength, false); // Line to the inner arc's end point

  shape.lineTo(
    innerRadius * Math.cos(thetaStart + thetaLength),
    innerRadius * Math.sin(thetaStart + thetaLength)
  );
  shape.absarc(0, 0, innerRadius, thetaStart + thetaLength, thetaStart, true); // Close the path

  shape.lineTo(
    outerRadius * Math.cos(thetaStart),
    outerRadius * Math.sin(thetaStart)
  );

  const extrudeSettings = {
    curveSegments: 100,
    steps: 1,
    depth: E,
    bevelEnabled: false,
  };
  const extrudeSettings2 = {
    curveSegments: 100,
    steps: 1,
    depth: E2,
    bevelEnabled: false,
  };

  const extrudeGeometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
  const extrudeGeometryBottom = new THREE.ExtrudeGeometry(
    shape,
    extrudeSettings2
  );
  !Type.includes("s")
    ? extrudeGeometry.translate(0.5, 0, -(E / 2))
    : extrudeGeometry.translate(-0.5, 0, -(E / 2));
  extrudeGeometry.rotateX(-Math.PI / 2);
  extrudeGeometry.translate(0, -(E / 2) - 0.1, 0);
  !Type.includes("s")
    ? extrudeGeometryBottom.translate(0.5, 0, -(E / 2))
    : extrudeGeometryBottom.translate(-0.5, 0, -(E / 2));
  extrudeGeometryBottom.rotateX(-Math.PI / 2);
  Type.includes("CZE-20-1")
    ? extrudeGeometryBottom.translate(0, -(E / 2) - 0.2, 0)
    : extrudeGeometryBottom.translate(0, -(E / 2) - 0.1, 0);
  const ringMesh = new THREE.Mesh(extrudeGeometry, material);
  const ringMeshBottom = new THREE.Mesh(extrudeGeometryBottom, material);
  ringMesh.position.set(0, EL, 0);
  ringMeshBottom.position.set(0, EL - H + D + 0.1, 0);

  let Group = new THREE.Group();
  Group.add(ringMesh);
  Group.add(ringMeshBottom);
  Group.quaternion.setFromAxisAngle(
    new THREE.Vector3(0, 1, 0),
    (-Math.PI / 180) * Degree
  );

  Group.userData.type = "JIAQIANGBAN";

  return Group;
};


let preWeldedPartBox3Arr = ref([])
let loadPlantformPreWeldedPartModelSingle = (data) => {
  let group = new THREE.Group();
  let model = ModelObj[data.Type].clone();
  model.translateZ(-(data.L2 / 100));
  model.translateY(data.EL / 100);
  model.netData = data;

  group.add(model);

  group.quaternion.setFromAxisAngle(
    new THREE.Vector3(0, 1, 0),
    (-Math.PI / 180) * data.Degree
  );

  let preWeldedPartBox3 =  new THREE.Box3(new THREE.Vector3(), new THREE.Vector3());
  preWeldedPartBox3.setFromObject(group);
  preWeldedPartBox3Arr.value.push({
    box3:preWeldedPartBox3,
    model:group,
    message:data
  })
  
  return group;
};

let loadDZEModelSingle = (data) => {
  let group = new THREE.Group();
  let model = ModelObj[data.Type].clone();

  model.position.y = data.EL / 100;
  model.position.z = -(data.L2 / 100);
  let { bottomBindScale, TriangleScale } = computerDZEData(data);

  model.children[1].scale.x = bottomBindScale;
  model.children[2].scale.z = TriangleScale;
  model.netData = data;
  group.add(model);
  group.quaternion.setFromAxisAngle(
    new THREE.Vector3(0, 1, 0),
    (-Math.PI / 180) * data.Degree
  );

  let preWeldedPartBox3 =  new THREE.Box3(new THREE.Vector3(), new THREE.Vector3());
  preWeldedPartBox3.setFromObject(group);
  preWeldedPartBox3Arr.value.push({
    box3:preWeldedPartBox3,
    model:group,
    message:data
  })
 
  return group;
};

let computerDZEData = (data) => {
  let bottomBindHeight = data.L1 / 100 - (0.55 + 0.7) + 1.5;
  let bottomBindScale = bottomBindHeight * 0.5;
  let TriangleScale = bottomBindScale - 0.5 + 1.09;
  return {
    bottomBindScale,
    TriangleScale,
  };
};

let loadPlantformPreWeldedPartModelSingleDemo = (data) => {
  let group = new THREE.Group();
  let model = ModelObj[data.Type].clone();
  model.netData = data;

  model.scale.set(2, 1, 1);
  group.add(model);
  group.position.set(0, 0, 0);

  return group;
};

watch(
  () => props.PlantformPreWeldedPart,
  async () => {
    if (
      Array.isArray(props.PlantformPreWeldedPart) &&
      props.PlantformPreWeldedPart[0] !== "初始数据"
    ) {
      ModelObj = await loadModelFn(props.PlantformPreWeldedPart);

      loadPlantformPreWeldedPartModel(props.PlantformPreWeldedPart);
    } else {
      ElMessage.error(props.PlantformPreWeldedPart);
    }
  },
  { immediate: true }
);
</script>

<style scoped>
.canvas {
  /* margin: 0 8px; */
  background: linear-gradient(to right, #0f0c29, #302b63, #24243e);
}
.box_model {
  background: linear-gradient(to right, #0f0c29, #302b63, #24243e);
}
.bottom_bar {
  background: #242829;
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  padding: 15px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.box_model_bg_button{
   opacity: 0;
  position: absolute;
  /* top:0px; */
  left:50px
}
</style>
